{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://course.rs/advance-practice1/intro.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 构建单线程 Web 服务器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 初始化工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "    Creating binary (application) `single_thread_00` package\n",
       "note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "! cargo new single_thread_00 --bin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1：解析首行 —— 写失败测试（Red）\n",
    "\n",
    "HTTP 请求的第一行形如 GET / HTTP/1.1。我们先写一个测试，要求把这行字符串解析为结构化数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cargo new single_thread_01 --bin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_01/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 1 test\n",
      "tests::parse_request_line_extracts_method_path_version --- FAILED\n",
      "\n",
      "failures:\n",
      "\n",
      "---- tests::parse_request_line_extracts_method_path_version stdout ----\n",
      "\n",
      "thread 'tests::parse_request_line_extracts_method_path_version' panicked at src/lib.rs:10:5:\n",
      "not implemented\n",
      "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n",
      "\n",
      "\n",
      "failures:\n",
      "    tests::parse_request_line_extracts_method_path_version\n",
      "\n",
      "test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "error: test failed, to rerun pass `--lib`\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_01 && cargo test parse_request_line_extracts_method_path_version -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2：实现最小逻辑（Green）\n",
    "\n",
    "只写足以通过测试的代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cargo new single_thread_02 --bin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_02/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_01/src/lib.rs\t2025-10-25 23:19:02.776806600 +0800\n",
      "+++ ./single_thread_02/src/lib.rs\t2025-10-25 23:20:14.762406300 +0800\n",
      "@@ -6,8 +6,17 @@\n",
      "     pub version: String,\n",
      " }\n",
      " \n",
      "-pub fn parse_request_line(_line: &str) -> RequestLine {\n",
      "-    unimplemented!()\n",
      "+pub fn parse_request_line(line: &str) -> RequestLine {\n",
      "+    let mut parts = line.split_whitespace();\n",
      "+    let method = parts.next().unwrap_or_default().to_string();\n",
      "+    let path = parts.next().unwrap_or_default().to_string();\n",
      "+    let version = parts.next().unwrap_or_default().to_string();\n",
      "+\n",
      "+    RequestLine {\n",
      "+        method,\n",
      "+        path,\n",
      "+        version,\n",
      "+    }\n",
      " }\n",
      " \n",
      " #[cfg(test)]\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_01/src/lib.rs ./single_thread_02/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 1 test\n",
      ".\n",
      "test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_02 && cargo test parse_request_line_extracts_method_path_version -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3：重构（Refactor）\n",
    "\n",
    "当前实现较简单，暂时无需额外重构，但我们可以加上一些错误防护测试，确保健壮性："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "source": [
    "- [lib.rs](./single_thread_03/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_02/src/lib.rs\t2025-10-25 23:20:14.762406300 +0800\n",
      "+++ ./single_thread_03/src/lib.rs\t2025-10-25 23:31:37.993747900 +0800\n",
      "@@ -37,4 +37,19 @@\n",
      "             }\n",
      "         );\n",
      "     }\n",
      "+\n",
      "+    #[test]\n",
      "+    fn parse_request_line_handles_missing_fields() {\n",
      "+        let line = \"GET /\";\n",
      "+        let parsed = parse_request_line(line);\n",
      "+\n",
      "+        assert_eq!(\n",
      "+            parsed,\n",
      "+            RequestLine {\n",
      "+                method: \"GET\".into(),\n",
      "+                path: \"/\".into(),\n",
      "+                version: \"\".into()\n",
      "+            }\n",
      "+        );\n",
      "+    }\n",
      " }\n",
      "\\ No newline at end of file\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_02/src/lib.rs ./single_thread_03/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 2 tests\n",
      "..\n",
      "test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_03 && cargo test -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 4：为响应构造写测试（Red）\n",
    "\n",
    "我们希望构造以下形式的响应字符串："
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "HTTP/1.1 200 OK\\r\\nContent-Length: 12\\r\\n\\r\\nHello World!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_04/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_03/src/lib.rs\t2025-10-25 23:31:37.993747900 +0800\n",
      "+++ ./single_thread_04/src/lib.rs\t2025-10-25 23:33:09.622392000 +0800\n",
      "@@ -19,6 +19,16 @@\n",
      "     }\n",
      " }\n",
      " \n",
      "+pub struct Response {\n",
      "+    pub status_line: String,\n",
      "+    pub headers: Vec<(String, String)>,\n",
      "+    pub body: String,\n",
      "+}\n",
      "+\n",
      "+pub fn build_response(_response: Response) -> String {\n",
      "+    unimplemented!()\n",
      "+}\n",
      "+\n",
      " #[cfg(test)]\n",
      " mod tests {\n",
      "     use super::*;\n",
      "@@ -52,4 +62,18 @@\n",
      "             }\n",
      "         );\n",
      "     }\n",
      "+\n",
      "+    #[test]\n",
      "+    fn build_response_serializes_struct_to_http_string() {\n",
      "+        let response = Response {\n",
      "+            status_line: \"HTTP/1.1 200 OK\".into(),\n",
      "+            headers: vec![(\"Content-Length\".into(), \"5\".into())],\n",
      "+            body: \"Hello\".into(),\n",
      "+        };\n",
      "+\n",
      "+        assert_eq!(\n",
      "+            build_response(response),\n",
      "+            \"HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\nHello\"\n",
      "+        );\n",
      "+    }\n",
      " }\n",
      "\\ No newline at end of file\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_03/src/lib.rs ./single_thread_04/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 1 test\n",
      "tests::build_response_serializes_struct_to_http_string --- FAILED\n",
      "\n",
      "failures:\n",
      "\n",
      "---- tests::build_response_serializes_struct_to_http_string stdout ----\n",
      "\n",
      "thread 'tests::build_response_serializes_struct_to_http_string' panicked at src/lib.rs:29:5:\n",
      "not implemented\n",
      "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n",
      "\n",
      "\n",
      "failures:\n",
      "    tests::build_response_serializes_struct_to_http_string\n",
      "\n",
      "test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s\n",
      "\n",
      "error: test failed, to rerun pass `--lib`\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_04 && cargo test build_response_serializes_struct_to_http_string -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 5：实现最小逻辑（Green）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_05/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_04/src/lib.rs\t2025-10-25 23:33:09.622392000 +0800\n",
      "+++ ./single_thread_05/src/lib.rs\t2025-10-26 00:33:39.373679400 +0800\n",
      "@@ -25,8 +25,18 @@\n",
      "     pub body: String,\n",
      " }\n",
      " \n",
      "-pub fn build_response(_response: Response) -> String {\n",
      "-    unimplemented!()\n",
      "+pub fn build_response(response: Response) -> String {\n",
      "+    let mut http = response.status_line;\n",
      "+    http.push_str(\"\\r\\n\");\n",
      "+\n",
      "+    for (key, value) in response.headers {\n",
      "+        http.push_str(&format!(\"{key}: {value}\\r\\n\"));\n",
      "+    }\n",
      "+\n",
      "+    http.push_str(\"\\r\\n\");\n",
      "+    http.push_str(&response.body);\n",
      "+\n",
      "+    http\n",
      " }\n",
      " \n",
      " #[cfg(test)]\n",
      "@@ -76,4 +86,4 @@\n",
      "             \"HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\nHello\"\n",
      "         );\n",
      "     }\n",
      "-}\n",
      "\\ No newline at end of file\n",
      "+}\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_04/src/lib.rs ./single_thread_05/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 3 tests\n",
      "...\n",
      "test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_05 && cargo test -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 6：重构与补充测试（Refactor）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_06/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_05/src/lib.rs\t2025-10-26 00:33:39.373679400 +0800\n",
      "+++ ./single_thread_06/src/lib.rs\t2025-10-26 00:36:29.509627200 +0800\n",
      "@@ -86,4 +86,19 @@\n",
      "             \"HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\nHello\"\n",
      "         );\n",
      "     }\n",
      "+\n",
      "+\n",
      "+    #[test]\n",
      "+    fn build_response_allows_empty_headers() {\n",
      "+        let response = Response {\n",
      "+            status_line: \"HTTP/1.1 404 NOT FOUND\".into(),\n",
      "+            headers: vec![],\n",
      "+            body: \"Not Found\".into(),\n",
      "+        };\n",
      "+\n",
      "+        assert_eq!(\n",
      "+            build_response(response),\n",
      "+            \"HTTP/1.1 404 NOT FOUND\\r\\n\\r\\nNot Found\"\n",
      "+        );\n",
      "+    }\n",
      " }\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_05/src/lib.rs ./single_thread_06/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 4 tests\n",
      "....\n",
      "test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_06 && cargo test -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 7：为业务逻辑写测试（Red）\n",
    "\n",
    "我们希望 `route_request` 根据请求路径返回不同的文件名和状态码。例如：`GET /` 返回 `hello.html`，其他路径返回 `404.html`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_07/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_06/src/lib.rs\t2025-10-26 00:36:29.509627200 +0800\n",
      "+++ ./single_thread_07/src/lib.rs\t2025-10-26 00:39:38.025597700 +0800\n",
      "@@ -39,6 +39,15 @@\n",
      "     http\n",
      " }\n",
      " \n",
      "+pub struct RouteMatch {\n",
      "+    pub status_line: &'static str,\n",
      "+    pub filename: &'static str,\n",
      "+}\n",
      "+\n",
      "+pub fn route_request(_request: &RequestLine) -> RouteMatch {\n",
      "+    unimplemented!()\n",
      "+}\n",
      "+\n",
      " #[cfg(test)]\n",
      " mod tests {\n",
      "     use super::*;\n",
      "@@ -101,4 +110,32 @@\n",
      "             \"HTTP/1.1 404 NOT FOUND\\r\\n\\r\\nNot Found\"\n",
      "         );\n",
      "     }\n",
      "+\n",
      "+    #[test]\n",
      "+    fn route_request_returns_root_page() {\n",
      "+        let request = RequestLine {\n",
      "+            method: \"GET\".into(),\n",
      "+            path: \"/\".into(),\n",
      "+            version: \"HTTP/1.1\".into(),\n",
      "+        };\n",
      "+\n",
      "+        let route = route_request(&request);\n",
      "+\n",
      "+        assert_eq!(route.status_line, \"HTTP/1.1 200 OK\");\n",
      "+        assert_eq!(route.filename, \"hello.html\");\n",
      "+    }\n",
      "+\n",
      "+    #[test]\n",
      "+    fn route_request_returns_404_for_unknown_path() {\n",
      "+        let request = RequestLine {\n",
      "+            method: \"GET\".into(),\n",
      "+            path: \"/unknown\".into(),\n",
      "+            version: \"HTTP/1.1\".into(),\n",
      "+        };\n",
      "+\n",
      "+        let route = route_request(&request);\n",
      "+\n",
      "+        assert_eq!(route.status_line, \"HTTP/1.1 404 NOT FOUND\");\n",
      "+        assert_eq!(route.filename, \"404.html\");\n",
      "+    }\n",
      " }\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_06/src/lib.rs ./single_thread_07/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cd single_thread_07 && cargo test -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 8：实现（Green）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [lib.rs](./single_thread_07/src/lib.rs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./single_thread_07/src/lib.rs\t2025-10-26 00:39:38.025597700 +0800\n",
      "+++ ./single_thread_08/src/lib.rs\t2025-10-26 00:41:18.164798400 +0800\n",
      "@@ -44,8 +44,21 @@\n",
      "     pub filename: &'static str,\n",
      " }\n",
      " \n",
      "-pub fn route_request(_request: &RequestLine) -> RouteMatch {\n",
      "-    unimplemented!()\n",
      "+pub fn route_request(request: &RequestLine) -> RouteMatch {\n",
      "+    match request {\n",
      "+        RequestLine {\n",
      "+            method,\n",
      "+            path,\n",
      "+            ..\n",
      "+        } if method == \"GET\" && path == \"/\" => RouteMatch {\n",
      "+            status_line: \"HTTP/1.1 200 OK\",\n",
      "+            filename: \"hello.html\",\n",
      "+        },\n",
      "+        _ => RouteMatch {\n",
      "+            status_line: \"HTTP/1.1 404 NOT FOUND\",\n",
      "+            filename: \"404.html\",\n",
      "+        },\n",
      "+    }\n",
      " }\n",
      " \n",
      " #[cfg(test)]\n"
     ]
    }
   ],
   "source": [
    "! diff -u ./single_thread_07/src/lib.rs ./single_thread_08/src/lib.rs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 6 tests\n",
      "......\n",
      "test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_08 && cargo test -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 整合：读取 TCP 流并组装响应"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 2 tests\n",
      "..\n",
      "test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 2 tests\n",
      "..\n",
      "test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 2 tests\n",
      "..\n",
      "test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n",
      "\n",
      "running 0 tests\n",
      "\n",
      "test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n",
      "\n"
     ]
    }
   ],
   "source": [
    "! cd single_thread_final && cargo test -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 构建多线程 Web 服务器\n",
    "\n",
    "- https://course.rs/advance-practice1/multi-threads.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 优雅关闭和资源清理\n",
    "\n",
    "- https://course.rs/advance-practice1/graceful-shutdown.html"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "C++17",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
